package com.cloud.pole.weixin.controller;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cloud.pole.common.constant.CommonConstants;
import com.cloud.pole.common.exception.BaseException;
import com.cloud.pole.common.exception.ParamException;
import com.cloud.pole.common.msg.ApiRestResponse;
import com.cloud.pole.common.util.RegexUtils;
import com.cloud.pole.weixin.biz.WxAppBiz;
import com.cloud.pole.weixin.model.entity.WxApp;
import com.cloud.pole.weixin.model.entity.WxUser;
import com.cloud.pole.weixin.service.WechatApiService;
import com.cloud.pole.weixin.util.wechat.SHA1;
import com.cloud.pole.weixin.util.wechat.WxCommonConstants;
import com.cloud.pole.weixin.wechat.domain.BaseRespMsg;
import com.cloud.pole.weixin.wechat.handler.DefaultSession;
import com.cloud.pole.weixin.wechat.handler.HandleMessageAdapter;
import com.cloud.pole.weixin.wechat.message.Msg;
import com.cloud.pole.weixin.wechat.message.Msg4Event;
import com.cloud.pole.weixin.wechat.message.Msg4Text;

import lombok.extern.slf4j.Slf4j;

@Controller
@RequestMapping("wx/front")
@Slf4j
public class WechatApiController {
	@Autowired
	private WechatApiService wechatApiService;
	@Autowired
	private WxAppBiz wxAppBiz;
	
    @RequestMapping(value = "/weChat/{id}", method = RequestMethod.GET)
    public void tokenValid(
    		HttpServletRequest request, HttpServletResponse response,
    		@RequestParam(name = "signature", defaultValue = "") String signature,
    		@RequestParam(name = "echostr", defaultValue = "") String echostr,
    		@RequestParam(name = "timestamp", defaultValue = "") String timestamp,
    		@RequestParam(name = "nonce", defaultValue = "") String nonce,
    		@PathVariable int id){   	
    	try {
    		log.info("微信加密签名signature:" + signature);
    		log.info("随机字符串echostr:" + echostr);
    		log.info("时间戳timestamp:" + timestamp);
    		log.info("随机数nonce:" + nonce);
    		
    		WxApp wxApp = wxAppBiz.selectByPrimaryKey(id);
    		if(wxApp == null) {
    			log.error("appId["+id+"]应用错误");
    		}
    		String[] str = {wxApp.getToken(), timestamp, nonce };
    		Arrays.sort(str); // 字典序排序
    		String bigStr = str[0] + str[1] + str[2];
    		// SHA1加密
    		String digest = new SHA1().getDigestOfString(bigStr.getBytes()).toLowerCase();
    		// 确认请求来至微信
    		if (digest.equals(signature)) {
    			log.info("微信token验证成功");
    			response.getWriter().print(echostr);
    		}else{
    			log.info("微信token验证失败");
    			response.getWriter().print("");
    		}
       	} catch (Exception e) {
			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", e.getMessage(), e);
			e.printStackTrace();
		}
    }
    
    /**
     * 微信消息处理
     */
    @RequestMapping(value = "/weChat/{id}", method = RequestMethod.POST)
    public void weChat(HttpServletRequest request, HttpServletResponse response){   	
    	try {
    		InputStream is = request.getInputStream();
            OutputStream os = response.getOutputStream();
            final DefaultSession session = DefaultSession.newInstance();
            session.addOnHandleMessageListener(new HandleMessageAdapter() {
                @Override
                public void onTextMsg(Msg4Text msg) {
                    log.info("收到来自" + msg.getFromUserName() + "的微信消息：" + msg.getContent());
                    String openId = msg.getFromUserName();
                    String originalId = msg.getToUserName();
                    try {
                    	Msg replyMsg = wechatApiService.getReplyMsg(Msg.MSG_TYPE_TEXT, msg.getContent(), openId, originalId);
                    	if(replyMsg != null) {
                            session.callback(replyMsg);
                    	}
                    } catch (Exception ex) {
            			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", ex.getMessage(), ex);
                        ex.printStackTrace();
                    }
                    return;
                }
                @SuppressWarnings("unused")
                @Override
                public void onEventMsg(Msg4Event msg) {
                	log.info("msg.SCAN：" + msg.SCAN);
                    if (StringUtils.equalsIgnoreCase(msg.getEvent(), Msg4Event.SUBSCRIBE)) {
                        log.info("收到微信订阅事件：");
                        log.info("FromUserName：" + msg.getFromUserName());
                        log.info("ToUserName：" + msg.getToUserName());
                        log.info("CreateTime：" + msg.getCreateTime());
                        String openId = msg.getFromUserName();
                        String originalId = msg.getToUserName();
                        try {
                            log.info("openId：" + openId);
                            log.info("originalId：" + originalId);
                        	wechatApiService.subscribeWxUser(openId, originalId);
                        	Msg replyMsg = wechatApiService.getReplyMsg(msg.getEvent(), "", openId, originalId);
                        	if(replyMsg != null) {
                                session.callback(replyMsg);
                        	}
//                        	Msg4ImageText imageText = new Msg4ImageText();
//                        	imageText.setFromUserName(originalId);
//                        	imageText.setToUserName(openId);
//                        	Data4Item item = new Data4Item();
//                        	item.setDescription("商城系统1");
//                        	item.setPicUrl("http://shop.yunji999.com/images/goods/RYQWO4GADCSSDVI1552355122594.jpg");
//                        	item.setTitle("商城1");
//                        	item.setUrl("http://shop.yunji999.com");
//                        	imageText.addItem(item);
//                        	Data4Item item2 = new Data4Item();
//                        	item2.setDescription("商城系统2");
//                        	item2.setPicUrl("http://shop.yunji999.com/images/goods/KEQIRVZSBQUPOYR1552357849744.jpg");
//                        	item2.setTitle("商城2");
//                        	item2.setUrl("http://shop.yunji999.com");
//                        	imageText.addItem(item2);
//                        	session.callback(imageText);
                        } catch (Exception ex) {
                			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", ex.getMessage(), ex);
                            ex.printStackTrace();
                        }
                        return;
                    }
                    if (StringUtils.equalsIgnoreCase(msg.getEvent(), Msg4Event.UNSUBSCRIBE)) {
                    	log.info("收到微信取消事件：");
                    	log.info("FromUserName：" + msg.getFromUserName());
                    	log.info("ToUserName：" + msg.getToUserName());
                    	log.info("CreateTime：" + msg.getCreateTime());
                        String openId = msg.getFromUserName();
                        String originalId = msg.getToUserName();
                        try {
                        	wechatApiService.unSubscribeWxUser(openId, originalId);
                        } catch (Exception ex) {
                			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", ex.getMessage(), ex);
                            ex.printStackTrace();
                        }
                        return;
                    }
                    if (StringUtils.equalsIgnoreCase(msg.getEvent(), Msg4Event.CLICK)) {
                    	log.info("收到微信点击事件：" + msg.getEventKey());
                        String openId = msg.getFromUserName();
                        String originalId = msg.getToUserName();
                        try {
	                    	Msg replyMsg = wechatApiService.getReplyMsg(msg.getEvent(), "", openId, originalId);
	                    	if(replyMsg != null) {
	                            session.callback(replyMsg);
	                    	}
	                    } catch (Exception ex) {
	            			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", ex.getMessage(), ex);
	                        ex.printStackTrace();
	                    }
                        return;
                     }
                    if (StringUtils.equalsIgnoreCase(msg.getEvent(), Msg4Event.SCAN)) {
                    	log.info("getEventKey：" + msg.getEventKey());
                    	log.info("getTicket：" + msg.getTicket());
                    	log.info("getFromUserName：" + msg.getFromUserName());
                        if (log.isDebugEnabled()) {
                        	log.debug("收到微信扫描事件");
                        	log.debug("EventKey:" + msg.getEventKey());
                        }
                    }
                    
                }
            });
            //必须调用这两个方法
            //如果不调用close方法，将会出现响应数据串到其它Servlet中。
            session.process(is, os);//处理微信消息
            session.close();//关闭Session
       	} catch (Exception e) {
			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", e.getMessage(), e);
			e.printStackTrace();
		}
    }
    
    /**
     * 获取code，并重定向接口getWxUserInfo，code只能使用一次
     * @param request
     * @param response
     * @param wxAppId
     * @param gotoURL 前端需要跳转的地址
     */
    @RequestMapping(value = "/getCode")
    public void getCode(HttpServletRequest request, HttpServletResponse response, 
    		@RequestParam(defaultValue = "1") String wxAppId, 
    		@RequestParam(defaultValue = "") String gotoURL){
    	try {
			ParamException.err(StringUtils.isBlank(wxAppId), "wxAppId不能为空");	
			ParamException.err(StringUtils.isBlank(gotoURL), "gotoURL不能为空");			
			ParamException.err(!RegexUtils.isPositiveInteger(wxAppId), "wxAppId错误");		
			WxApp wxApp = wxAppBiz.selectByPrimaryKey(Integer.parseInt(wxAppId));
			if(wxApp == null || wxApp.getAppStatus().intValue() !=  WxApp.APP_STATUS_OK) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "wxAppId错误");
			}
			String redirectUri = wxApp.getRedirectUri() + "?wxAppId="+wxAppId+"&gotoURL=" + gotoURL;			
			response.sendRedirect("https://open.weixin.qq.com/connect/oauth2/authorize?appid="+wxApp.getAppId()+"&redirect_uri=" + URLEncoder.encode(redirectUri, "UTF-8") + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect");
    	} 
    	catch (Exception e) {
			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", e.getMessage(), e);
			e.printStackTrace();
		}
    }
    
    /**
     * 测试接受code接口
     * @param request
     * @param response
     * @param code
     */
    @RequestMapping(value = "/getCodeDemo")
    public void getCodeDemo(HttpServletRequest request, HttpServletResponse response,
    		@RequestParam(defaultValue = "") String code){
    	try {
			log.info("获取到code["+ code +"]");
    	} 
    	catch (Exception e) {
			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", e.getMessage(), e);
			e.printStackTrace();
		}
    }
    /**
     * 接受code地址，再跳转到前端
     * @param request
     * @param response
     * @param code
     * @param wxAppId
     * @param gotoURL 前端需要跳转的地址
     */
    @RequestMapping(value = "/getWxUserInfo")
    public void getWxUserInfo(HttpServletRequest request, HttpServletResponse response,
    		@RequestParam(defaultValue = "") String code,
    		@RequestParam(defaultValue = "1") String wxAppId, 
    		@RequestParam(defaultValue = "") String gotoURL){   	
    	try {
    		log.info("code=" + code);
    		log.info("wxAppId="+ wxAppId);
    		log.info("gotoURL=" + gotoURL);
    		if(StringUtils.isBlank(code)) {
    			log.error("code为空");
    		}
    		else if(StringUtils.isBlank(wxAppId)) {
    			log.error("wxAppId为空");
    		}
    		else if(StringUtils.isBlank(gotoURL)) {
    			log.error("gotoURL为空");
    		}
    		else {
    			WxUser wxUser = wechatApiService.getWxUserInfoByCode(code, Integer.parseInt(wxAppId));
    			response.sendRedirect(gotoURL + "?openId=" + wxUser.getOpenId());
    		}
    	} catch (BaseException e) {
			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", e.getMessage(), e);
			e.printStackTrace();
    	} catch (Exception e) {
			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", e.getMessage(), e);
			e.printStackTrace();
		}
    }
	
    /**
     * 前端主动接收到code，再调用接口获取微信用户资料
     * @param code
     * @param wxAppId
     * @return
     */
	@ResponseBody
    @RequestMapping(value = "/getUserInfo")
    public ApiRestResponse<WxUser> getWxUserInfoByCode(
    		@RequestParam(defaultValue = "") String code, 
    		@RequestParam(defaultValue = "1") String wxAppId){   	
    	try {
			ParamException.err(StringUtils.isBlank(code), "code不能为空");
			ParamException.err(StringUtils.isBlank(wxAppId), "wxAppId不能为空");			
			ParamException.err(!RegexUtils.isPositiveInteger(wxAppId), "wxAppId错误");			
			return ApiRestResponse.success(CommonConstants.STATUS_OK_MESSAGE, wechatApiService.getWxUserInfoByCode(code, Integer.parseInt(wxAppId)));
    	} catch (BaseException e) {
			return ApiRestResponse.fail(e.getStatus(), e.getMessage(), null);
		} catch (Exception e) {
			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", e.getMessage(), e);
			return ApiRestResponse.fail(CommonConstants.STATUS_ERROR_MESSAGE, null);
		}
    }
	
	@ResponseBody
    @RequestMapping(value = "/createMenu")
    public ApiRestResponse<BaseRespMsg> createMenu(    		
    		@RequestParam(defaultValue = "") String wxAppId, 
    		@RequestParam(defaultValue = "") String passWord){   	
    	try {
			ParamException.err(StringUtils.isBlank(wxAppId), "wxAppId不能为空");	
			ParamException.err(StringUtils.isBlank(passWord), "passWord不能为空");			
			if(!StringUtils.equals(passWord, "0000000000")) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "passWord错误");
			}
			ParamException.err(!RegexUtils.isPositiveInteger(wxAppId), "wxAppId错误");	
			
			return ApiRestResponse.success(CommonConstants.STATUS_OK_MESSAGE,  wechatApiService.createMenu(Integer.parseInt(wxAppId)));
    	} catch (BaseException e) {
			return ApiRestResponse.fail(e.getStatus(), e.getMessage(), null);
		} catch (Exception e) {
			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", e.getMessage(), e);
			return ApiRestResponse.fail(CommonConstants.STATUS_ERROR_MESSAGE, null);
		}
    }
	
	@ResponseBody
    @RequestMapping(value = "/subscribeWxUserTest")
    public ApiRestResponse<WxUser> subscribeWxUserTest(){   	
    	try {
        	wechatApiService.subscribeWxUser("oXY4v1OWYiL1_hwsAXhbjTs_W_cU", "gh_a162fab30df0");
			return ApiRestResponse.success(CommonConstants.STATUS_OK_MESSAGE, null);
    	} catch (BaseException e) {
			return ApiRestResponse.fail(e.getStatus(), e.getMessage(), null);
		} catch (Exception e) {
			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", e.getMessage(), e);
			return ApiRestResponse.fail(CommonConstants.STATUS_ERROR_MESSAGE, null);
		}
    }
	
	@ResponseBody
    @RequestMapping(value = "/getReplyMsgTest")
    public ApiRestResponse<Msg> getReplyMsgTest(    		
    		@RequestParam(defaultValue = "") String eventType,
    		@RequestParam(defaultValue = "") String eventKey,
    		@RequestParam(defaultValue = "") String originalId,
    		@RequestParam(defaultValue = "") String openId){   	
    	try {
        	Msg replyMsg = wechatApiService.getReplyMsg(eventType, eventKey, openId, originalId);
			return ApiRestResponse.success(CommonConstants.STATUS_OK_MESSAGE, replyMsg);
    	} catch (BaseException e) {
			return ApiRestResponse.fail(e.getStatus(), e.getMessage(), null);
		} catch (Exception e) {
			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", e.getMessage(), e);
			return ApiRestResponse.fail(CommonConstants.STATUS_ERROR_MESSAGE, null);
		}
    }
	
	@ResponseBody
	@RequestMapping(value="getWxShareInfo")
	public ApiRestResponse<Map<String, Object>> getWxShareInfo(
			@RequestParam(defaultValue = "") String url,
			@RequestParam(defaultValue = "1") String wxAppId) {
		try {
			ParamException.err(StringUtils.isBlank(url), "url不能为空");
			WxApp wxApp = wxAppBiz.selectByPrimaryKey(Integer.parseInt(wxAppId));
			if(wxApp == null || wxApp.getAppStatus().intValue() !=  WxApp.APP_STATUS_OK) {
				throw new BaseException(CommonConstants.STATUS_ERROR_CODE, "wxAppId错误");
			}
			Map<String, Object> result = WxCommonConstants.getWxShareInfo(url, wxApp);
			return ApiRestResponse.success(CommonConstants.STATUS_OK_MESSAGE, result);
		} catch (BaseException e) {
			return ApiRestResponse.fail(e.getStatus(), e.getMessage(), null);
		} catch (Exception e) {
			log.error(CommonConstants.STATUS_ERROR_MESSAGE + "{}", e.getMessage(), e);
			return ApiRestResponse.fail(CommonConstants.STATUS_ERROR_MESSAGE, null);
		}
	}
}
